/**
 * 
 */

/**
 * @author chenxu
 *
 */

import java.util.ArrayList;

import javafx.animation.ScaleTransition;
import javafx.application.Application;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.scene.Scene; 
import javafx.scene.layout.HBox;
import javafx.util.Duration;


public class Game extends Application {

	 public Deck deck = new Deck();
	 public Hand myHand = new Hand();
	 public Hand enemyHand = new Hand();
	 public Parade parade = new Parade();
	 public WasteArea myWaste = new WasteArea();
	 public WasteArea enemyWaste = new WasteArea();

	 
     VBox front = new VBox(30);
     AnchorPane back = new AnchorPane(front);

     HBox top = new HBox(20);
     HBox middle = new HBox(20);
     HBox bottom = new HBox(20);
     Scene scene = new Scene(back);
     
	 Button end = new Button("end?");
	 Text scores = new Text();
	 Text over = new Text("");

	 public boolean isMyTurn=true;
	 public boolean isLastTurn = false;
	 public boolean canListenOnMouse = true;
	 public int lastTurnCount = 0;
	 
	 ArrayList<Card> lastTwoCards = new ArrayList<Card>();
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        Application.launch(args);

	}

	 public void setDelegate(){
		 myHand.setDelegator(this);
		 enemyHand.setDelegator(this);
		 deck.setDelegator(this);
		 parade.setDelegator(this);
		 myWaste.setDelegate(this);
		 enemyWaste.setDelegate(this);
	 }
	
	 public void start(Stage stage) {
         // set this as delegator,each time Deck.java and Hand.java
		 // or other java class finish it's animation will
		 // stimulate related functions.
		 this.setDelegate();
		 
		 
		 
		 //Set View layout.The layout is top,middle,bottom three parts.
		 //Top area belongs to Ai.Middle puts the parade,deck and buttons.
		 //Bottom puts players' area.Hand's card is put in middle of 
		 //waste(score) area.
		 for(int i=0;i<3;i++){
			 top.getChildren().add(enemyWaste.at(i));
		 }
		 top.getChildren().addAll(enemyHand);
		 for(int i=3;i<6;i++){
			 top.getChildren().add(enemyWaste.at(i));
		 }
		 
		 for(int i=0;i<3;i++){
			 bottom.getChildren().add(myWaste.at(i));
		 }
		 bottom.getChildren().addAll(myHand);
		 for(int i=3;i<6;i++){
			 bottom.getChildren().add(myWaste.at(i));
		 }
		 
		 //set top gap
		 top.setLayoutY(20);
	
		 //layout buttons 
		 Button restart = new Button("restart");
		 Button showAI = new Button("show AI's card");
		 scores.setText("  Score\n  You:AI\n  0:0");
		 
		 VBox buttons = new VBox();
		 buttons.getChildren().addAll(restart,showAI,scores);
		 showAI.setOnMouseClicked(e->enemyHand.switchUpside());
		 restart.setOnMouseClicked(e->this.restart());
		 middle.getChildren().addAll(buttons, deck,parade);
		 middle.setPrefHeight(300);
		 
		 front.getChildren().addAll(top,middle,bottom);
		 front.setPrefSize(1200, 700);
		 front.setLayoutY(40);
		 
		 
		 
		 
		 //Some initialization:
		 //Init myHand and Ai's hand
		 for(int i=0;i<5;i++){
			 myHand.drawWithListener(deck.drawACard());
			 enemyHand.draw(deck.drawACard());
		 }
		 
		 //Init the parade
		 for(int i=0;i<6;i++){
			 parade.addCard(deck.drawACard());
		 }
		 
		 //set stage
         stage.setTitle("Alice in Wonderland");
         stage.setScene(scene);
         stage.show(); 
     }
	 
	
	 public void restart(){
		 deck.reset();
		 myHand.clear();
		 enemyHand.clear();
		 myWaste.clear();
		 enemyWaste.clear();
		 parade.clear();
		 isMyTurn = true;
		 isLastTurn = false;
		 canListenOnMouse = true;
		 lastTurnCount=0;
		 scores.setText("Score 0:0");
		 lastTwoCards.clear();
		 for(int i=0;i<5;i++){
			 myHand.drawWithListener(deck.drawACard());
			 enemyHand.draw(deck.drawACard());
		 }
		 //parade ������5���
		 for(int i=0;i<6;i++){
			 parade.addCard(deck.drawACard());
		 }
		 
		 back.getChildren().remove(over);
	 }

	public void newClickOnCard(Card cd){
		 if(isMyTurn && isLastTurn==false && canListenOnMouse){
			 
			 for(int i=parade.length();i>0;i--){
				 Card temp = parade.at(i-1);
				 temp.opacity();
			 }
			 myHand.newput(cd);
			 canListenOnMouse=false;
		 }
		 else if(isLastTurn == true){
			 this.LastTurn(cd);
		 }
	 }

	public void HangingOnCard(Card cd){
		 if(canListenOnMouse && !isLastTurn){
		 //������parade
			 cd.Bigger();
			 //safe card ������
			 for(int i=parade.length();i >parade.length()-cd.number && i>0;i--){
				 Card temp = parade.at(i-1);
				 temp.transparent();
			 }
			 //������������������
			 for(int i=parade.length()-cd.number;i>0;i--){
				 Card temp = parade.at(i-1);
				 if(temp.color==cd.color || temp.number<=cd.number){
					 temp.Bigger();
				 }
			 }
		 }
	 }
	 
	 public void ExitCard(Card cd){
		 if(canListenOnMouse && !isLastTurn){
			 cd.Smaller();
			 
			 for(int i=parade.length();i >parade.length()-cd.number && i>0;i--){
				 Card temp = parade.at(i-1);
				 temp.opacity();
			 }
			 for(int i=parade.length()-cd.number;i>0;i--){
				 Card temp = parade.at(i-1);
				 if(temp.color==cd.color || temp.number<=cd.number){
					 temp.Smaller();
				 }
			 }
		 }
	 }
	 
	
	 //������������:������������������>=2������������������������������1������������������
	 public void compareWaste(){
		 for(int i=0;i<6;i++){
			 WasteDeck my = myWaste.at(i);
			 WasteDeck enemy = enemyWaste.at(i);

			 if(my.size() >=enemy.size()+2){
				 my.turnAllBack();
			 }
			 else if(enemy.size() >=my.size()+2){
				 enemy.turnAllBack();
			 }

			 
			 //bug 
			 else if(enemy.size()-my.size() <2 && enemy.size()-my.size()>-2){
				 my.turnAllUp();
				 enemy.turnAllUp();
			 }
		 }
	 }
	 
		 
	 
	 public void handPutFinished(Card cd){
		parade.newAddCard(cd);
	 }
	 
	 public void paradeAddFinished(){
		 parade.removeWhatShouldBeRemoved();
	 }
	 
	 //������������������������
	 public void paradeRemoveFinished(ArrayList<Card> cards){
		 if(isMyTurn){
			 myWaste.addList(cards);
		 }
		 else{
			 enemyWaste.addList(cards);
		 }
		 
		 this.compareWaste();
	 }
	 
	 public  void wasteAddFinished(){

		 this.setScore();
		 this.shouldEnterLastTurn();

		 if(!isLastTurn ){
			 if(isMyTurn){
				 this.AiClick();
				 if(deck.size()!=0){
					 if(lastTurnCount<=1){
						 myHand.drawWithListener(deck.drawACard());
					 }
				 }
				 isMyTurn = false;
			 }
			 else {
				 if(deck.size()!=0){
					 if(lastTurnCount<=1){
						 enemyHand.draw(deck.drawACard());
					 }
				 }
				 isMyTurn =true;
				 canListenOnMouse=true;
			 }
		 }		 
		 
		 
	 }
	 
	 public void setScore(){
		 scores.setText("  Score\n  You:AI\n  "+myWaste.totalScore()+":"+enemyWaste.totalScore());
	 }
	 
	 public void AiClick(){
			 enemyHand.newput(enemyHand.at(AiFindMin()));
		
	 }
	 
	 public int AiFindMin(){
		//find the card which cause min score increase
		 int minIncrease=10000000;
		 int minIndex=0;
		 //try every card
		 for(int i=0;i<enemyHand.size();i++){
			 Card cd = enemyHand.at(i);
			 //this card's increase
			 int increase = 0;

			 //find cards will be influenced in parade
			 for(int j=parade.length()-cd.number;j>0;j--){
				 Card temp = new Card(parade.at(j-1));
				 //cards in parade which follow the rules:
				 //out of safe area--->1.same color
				 //                    2.smaller or same number
				 if(temp.color==cd.color || temp.number<=cd.number){
					 increase += temp.number;	 
				 }
			 } 
			 //mark the min card's index
			 if(minIncrease>increase){
				 minIndex = i;
				 minIncrease = increase;
			 }
		 }
		 return minIndex;
	 }
	
	 
	 //������������������������
	 public void shouldEnterLastTurn(){
		 if(deck.size() == 0 || myWaste.collectSix() || enemyWaste.collectSix()){
			 lastTurnCount++;
			 if(lastTurnCount == 1){
				 //	notice last turn
				 Text notice = new Text("LAST TURN!!");
				 notice.setFont(new Font(100));
				 back.getChildren().add(notice);
				 notice.setLayoutX(400);
				 notice.setLayoutY(400);

				 ScaleTransition flow = new ScaleTransition();
				 flow.setNode(notice);
				 flow.setToX(1.1);
				 flow.setToY(1.1);
				 flow.setDuration(Duration.millis(500));
				 flow.autoReverseProperty().setValue(true);
				 flow.play();
				 flow.setOnFinished(e->back.getChildren().remove(notice));
				 }
			 if(lastTurnCount == 3){
				 isLastTurn=true;
			 }
		 }
	 }

	public void LastTurn(Card cd){
		end.setOnMouseClicked(e->end());
		myHand.getChildren().remove(end);
		
		if(cd.isSelected==true){
			cd.Smaller();
			lastTwoCards.remove(cd);
			
		}
		else{
			if(lastTwoCards.size()<1){
				cd.Bigger();
				lastTwoCards.add(cd);
			}
			else if(lastTwoCards.size()==1){ 
				cd.Bigger();
				lastTwoCards.add(cd);
				myHand.getChildren().add(end);
			}
			else{	
				myHand.getChildren().add(end);
			}
		}
		
	 }

	public void end() {
		 System.out.println("GAME:GAME Ended");
		 over.setFont(new Font(100));
		 
	 
		 //hide last two cards' 
		 int one=0;
		 int two=0;
		 for(int m=0;m<enemyHand.size();m++){
			 Card cd = enemyHand.at(m);
			 //������parade���������	 
			 //������������������������������
			 if(cd.number <= enemyHand.at(one).number || cd.number <= enemyHand.at(two).number){
				 if(enemyHand.at(one).number>= enemyHand.at(two).number){
					 one = m;
				 }
				 else{
					 two = m;
				 }
			 }
			
		 }
		 Card temp = enemyHand.at(one);
		 enemyHand.put(temp);
		 enemyWaste.addCard(temp);
		 if(one < two){
			 two--;
		 }
		 
		 temp = enemyHand.at(two);
		 enemyHand.put(temp);
		 enemyWaste.addCard(temp);
		 
		 
		 //������������������
		 for(int i=0;i<2;i++){
			 Card mycard = lastTwoCards.get(i);
			 myHand.put(mycard);
			 myWaste.addCard(mycard);
		 }
		 
		 this.compareWaste();
		 
		
		 int myscore = myWaste.totalScore();
		 int enemyscore = enemyWaste.totalScore();
		 scores.setText("score "+myscore+":"+enemyscore);
		 
		 //������������
		 if(myscore>enemyscore){
			 over.setText("YOU LOSE");
		 }
		 else if(myscore<enemyscore){
			 over.setText("YOU WIN");
		 }
		 else{
			 over.setText("TIE");
		 }
		 over.setLayoutX(400);
		 over.setLayoutY(400);
		 back.getChildren().add(over);
	 }
	 
	
}
